package mainPNN;

import java.util.ArrayList;

import util.Constantes;
import util.PadraoTreinamento;
import util.Util;

public class MinimalSpanningTree {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ArrayList<PadraoTreinamento> padroes = Util.getTrainingData(Constantes.GET_NM_PATH_DATASET + "spanningtree.data");
		MinimalSpanningTree mst = new MinimalSpanningTree();
		double b[] = mst.teste(padroes);
		for (double d : b) {
			System.out.println(d);
		}

	}
	
	public double[] teste(ArrayList<PadraoTreinamento> pArrayPadraoTreinamento) {
		//ArrayList<PadraoTreinamento> A = new ArrayList<PadraoTreinamento>();
		ArrayList<PadraoTreinamento> Ba = pArrayPadraoTreinamento;
		
		double b[] = new double[Ba.size()];
		
		//Init
		PadraoTreinamento A[] = new PadraoTreinamento[Ba.size()];
		PadraoTreinamento B[] = new PadraoTreinamento[Ba.size()];
		for (int i = 0; i < Ba.size(); i++) {
			B[i] = Ba.get(i);
			b[i] = 1000000.0d;
		}
		
		//1) Start with an arbitrary point tj in B* and assign it to A*.
		//PadraoTreinamento tj = Util.getPadraoAleatorio(B, true);
		int j = 0;
		PadraoTreinamento tj = B[j];
		B[j] = null;
		A[j] = tj;
		
		while(temPrototipos(B)) {
			//2) For all points tk in B* such that class(tk) != class(tj), update bk to be the distance d(tk, tj) 
			//between tk and tj) if this distance is smaller than the present bk. Otherwise, bk in unchanged.
			for(int i = 0; i < B.length;  i++) {
				PadraoTreinamento tk = B[i];
				if (tk != null && tk.getClasse() != A[j].getClasse()) {
					Double distanciaOutraClasse = Util.getDistanciaEuclidiana(tk, A[j]);
					if (distanciaOutraClasse.doubleValue() < b[i]) {
						b[i] = distanciaOutraClasse;
					}
				}
			}
	
			//3) Among all points in B*, find a point ts which has the smallest bs associated with it.
			int s = Util.getMenorValor(b, B);
			PadraoTreinamento ts = B[s];
			
			PadraoTreinamento padraoA = Util.getPadraoMaisProximo(ts, A);
			
			//4) If tj is not the nearest point to ts such that the classes of tj and ts are different, go to 6). Otherwise, continue.
			if (A[j] == padraoA && A[j].getClasse() != ts.getClasse()) {
				//5) Check whether or not d(tj, ts) is less than bj. If no, go to 6). If yes, let bj = d(tj, ts) and continue.
				double distanciaTjTs = Util.getDistanciaEuclidiana(A[j], ts);
				if (distanciaTjTs < b[j]) {
					b[j] = distanciaTjTs;
				}
			}
	
			//6) Let j = s, move ts from B* to A*, and go to 2) until B* is empty. When B* is empty, the final b1, b2, ..., bm are the desired ones.
			j = s;
			A[s] = ts;
			B[s] = null;
		}
		
		return b;
	}

	private boolean temPrototipos(PadraoTreinamento[] pArray) {
		for (int i = 0; i < pArray.length; i++) {
			PadraoTreinamento padraoTeste = pArray[i];
			if(padraoTeste != null) {
				return true;
			}
		}
		
		return false;
	}
}

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	